package logica.util;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import modelo.DTO.DTODataMining;
import weka.clusterers.ClusterEvaluation;
import weka.clusterers.SimpleKMeans;
import weka.clusterers.XMeans;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;
/**
 *
 * @author Ion B. Padilla
 */
public class ClusterUtil {

    private ArrayList<DTODataMining> visitasAlumnos;
    private Instances instancia;
    private Instances instanciaEntera;
    private FastVector vectorAtributos;
    private ClusterEvaluation eval;
    private XMeans xMeans;
    private ArrayList<ArrayList<DTODataMining>> listaElementos,listaElementosFiltrada;
    private int numeroCluster;
    private double etiquetasClusters[];




    /**
     * Constructor de cluster util que setea las variables miembro
     * @param visitasAlumnos una lista con los nombres de todos los alumnos del curso
     * @param listaElementos matriz con todos las interacciones de los usuarios por registro
     * @param vectorAtributos Vector con los atributos del cluster
     * @param numeroCluster numero de clusters
     */
    public ClusterUtil(ArrayList<DTODataMining> visitasAlumnos, ArrayList<ArrayList<DTODataMining>> listaElementos, FastVector vectorAtributos, int numeroCluster) {
        //visitas alumnos es la lista de alumnos que tomamos de referencia
        this.visitasAlumnos = visitasAlumnos;
        this.listaElementos = listaElementos;
        this.vectorAtributos=vectorAtributos;
        this.numeroCluster=numeroCluster;
    }
    /**
     * Crea las instancias partiendo de las interacciones para luego usarlas en weka
     */ 
    private void createInstancias() {

     /*  for (int i=0;i<listaElementosFiltrada.get(0).size();i++){
                double [] valores=new double [listaElementosFiltrada.size()];
                for (int j=0;j<listaElementosFiltrada.size();j++){
                    valores[j]=Float.parseFloat(((DTODataMining)listaElementosFiltrada.get(j).get(i)).getCliks());
                }
                instancia.add(new Instance(1.0,valores));
        }*/
//        crearCSV();

        for (int i=0;i<visitasAlumnos.size();i++){
                double [] valores=new double [listaElementos.size()];
                for (int j=0;j<listaElementos.size();j++){
                    valores[j]=Float.parseFloat(((DTODataMining)listaElementos.get(j).get(i)).getCliks());
                     System.out.print(listaElementos.get(0).get(i).getNombre());
                System.out.print(";");
                System.out.print(listaElementos.get(0).get(i).getCliks()+"\n");
                }
                instancia.add(new Instance(1.0,valores));
        }

    }

  /*  public void crearCSV(){

        String temporal = "";
        String tmp;
       
        try {
          BufferedWriter  bw = new BufferedWriter(new FileWriter("informacion.csv"));
            for (int i = 0; i < listaElementos.get(0).size(); i++) {
                bw.write(listaElementos.get(0).get(i).getNombre());
                bw.write(";");
                bw.write(listaElementos.get(0).get(i).getCliks()+"\n");

                temporal=temporal + listaElementos.get(0).get(i).getNombre();
                temporal=temporal + ';';
                temporal=temporal + listaElementos.get(0).get(i).getCliks() + "\n";
                

            }
            bw.close();
        } catch (IOException ex) {
            Logger.getLogger(ClusterUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
    }*/

    public double [] etiquetarCluster (Instances centroide){

        double arrayClusters[] = new double[centroide.numInstances()];

        for (int i=0;i<centroide.numInstances();i++){

            arrayClusters[i]=0;

            for (int j=0;j<centroide.instance(i).numAttributes();j++){
                arrayClusters[i]=arrayClusters[i]+centroide.instance(i).value(j);
            }
        }
       return arrayClusters;
    }

  /*  public void crearFiltro(Instances instancia) throws Exception{
          RandomizeFilter Randomilter = new RandomizeFilter();
          for (int i = 0; i < instancia.numInstances(); i++) {
            filter.input(instancia.instance(i));
          }
          filter.batchFinished();
         /* Instances newData = filter.outputFormat();
          Instance processed;
          while ((processed = filter.output()) != null) {
            newData.add(processed);
          }
    }*/


    /**
     * Metodo para crear los clusters, antes de ejecutarlo hemos de haber creado las instancias correctamente, usando
     * addElement() por cada atributo
     */



   public double[] createCluster (){

      instancia=new Instances("rel",vectorAtributos,10);//numero 10 o es el total de atributos
      // instancia=new Instances("rel_entera",vectorAtributos,10);//numero 10 o es el total de atributos
        //añadimos cada instancia a la lista de instancias
       createInstancias();
     /*   try {
            crearFiltro(instancia);
        } catch (Exception ex) {
            Logger.getLogger(ClusterUtil.class.getName()).log(Level.SEVERE, null, ex);
        }*/
        try {

            SimpleKMeans cluster = new SimpleKMeans();
            cluster.setNumClusters(numeroCluster);
           // cluster.setMaxIterations(100);
            cluster.buildClusterer(instancia);

            //añadido para saber centros de cluster
            int[] tamanoClusters = cluster.getClusterSizes();
            Instances centroides = cluster.getClusterCentroids();
            Instance centroide;

            System.out.println("Centroides k-means ...");
            for(int i=0; i < cluster.numberOfClusters(); i++){
                centroide = centroides.instance(i);
                System.out.print("Cluster "+cluster+" ("+tamanoClusters[i]+" instancias): ");
                System.out.println("Centroide["+centroide.toString()+"]");
            }
            System.out.println();

            if (cluster.numberOfClusters()==1){
                etiquetasClusters = new double[3];
                etiquetasClusters[1]=0;
                etiquetasClusters[2]=0;
                etiquetasClusters[3]=0;
            }
            else etiquetasClusters=etiquetarCluster(centroides);

            eval=new ClusterEvaluation();
            eval.setClusterer(cluster);
            eval.evaluateClusterer(instancia);


           double[] listaClusters=   eval.getClusterAssignments();
           System.out.println("Imprimir lista de clusters");

           for (int i=0;i<listaClusters.length;i++){
               System.out.println(listaClusters[i]);
            }

            //metodo para visualizar el cluster en caso necesario
          //  DataMiningHelper dmh = new DataMiningHelper();
          //  dmh.visualizarCluster(xMeans, instancia, eval);
           // dmh.visualizarCluster(cluster, instancia, eval);
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            Logger.getLogger(ClusterUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
       return etiquetasClusters;
   }
   /**
     * Devuelve el objeto eval
     */
   public ClusterEvaluation getEval() {
        return eval;
    }
    /**
     * Setea el objeto eval
     */
    public void setEval(ClusterEvaluation eval) {
        this.eval = eval;
    }
    /**
     * Devuelve la instancia
     */
    public Instances getInstancia() {
        return instancia;
    }
    public Instances getInstanciaEntera() {
        return instanciaEntera;
    }
    public void setInstanciaEntera(Instances instanciaEntera) {
        this.instanciaEntera = instanciaEntera;
    }
    /**
     * Setea la instancia
     */
    public void setInstancia(Instances instancia) {
        this.instancia = instancia;
    }
}

